﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AssemblyInfoEditor.VersionManagement
{
    public class ManagedVersion
    {
        public ManagedVersion()
        {
            BaseDifferenceDate = new DateTime(1975, 12, 31, 23, 59, 59);
        }

        public IncrementStyle BuildIncrementStyle { get; set; }

        public int MajorVersion { get; set; }

        public int MinorVersion { get; set; }

        public int Build { get; set; }

        public int Revision { get; set; }

        public IncrementStyle RevisionIncrementStyle { get; set; }

        private DateTime BaseDifferenceDate { get; set; }

        /// <summary>
        /// Returns a string representation of the ManagedVersion object.
        /// </summary>
        public override string ToString()
        {
            return String.Format("{0}.{1}.{2}.{3}", MajorVersion.ToString(), MinorVersion.ToString(), Build.ToString(), Revision.ToString());
        }

        public void Increment(DateTime buildStart)
        {
            Build = CalculateIncrementation(Build, buildStart, BuildIncrementStyle);

            Revision = CalculateIncrementation(Revision, buildStart, RevisionIncrementStyle);
        }

        private int CalculateIncrementation(int baseValue, DateTime buildStart, IncrementStyle incrementStyle)
        {
            int deltaYears = buildStart.Year - BaseDifferenceDate.Year;
            DateTime dayStart = new DateTime(buildStart.Year, buildStart.Month, buildStart.Day, 0, 0, 0);

            switch (incrementStyle)
            {
                case IncrementStyle.None:
                    // Do nothing, leave the user-set value alone
                    return baseValue;

                case IncrementStyle.AddOne:
                    return baseValue++;

                case IncrementStyle.DayStamp:
                    return buildStart.Day;

                case IncrementStyle.DeltaBaseDate:
                    DateTime length = TimeSpanHelper.GetDateSpanLength(buildStart, BaseDifferenceDate);
                    return Int32.Parse(String.Format("{0}{1:00}", (length.Year * 12) + length.Month, length.Day));

                case IncrementStyle.DeltaBaseYear:
                    return deltaYears;

                case IncrementStyle.DeltaBaseYearDayOfYear:
                    return Int32.Parse(String.Format("{0}{1:000}", deltaYears, buildStart.DayOfYear));

                case IncrementStyle.MonthAndDayStamp:
                    return Int32.Parse(String.Format("{0}{1}", buildStart.Month, buildStart.Day));

                case IncrementStyle.MonthStamp:
                    return buildStart.Month;

                case IncrementStyle.TimeStamp:
                    return Int32.Parse(String.Format("{0:00}{1:00}", buildStart.Hour, buildStart.Minute));

                case IncrementStyle.YearDayOfYear:
                    return Int32.Parse(String.Format("{0}{1:000}", buildStart.ToString("yy"), buildStart.DayOfYear));

                case IncrementStyle.YearDecadeStamp:
                    return Int32.Parse(buildStart.ToString("yy"));

                case IncrementStyle.YearStamp:
                    return buildStart.Year;

                case IncrementStyle.DeltaHours:
                    return (int)buildStart.Subtract(BaseDifferenceDate).TotalHours;

                /*case IncrementStyle.DeltaHoursPlusMinutesOfDay:
                    return (int)buildStart.Subtract(BaseDifferenceDate).TotalHours + (int)buildStart.Subtract(dayStart).TotalMinutes;

                case IncrementStyle.DeltaDaysAndMinutesOfDay:
                    return Int32.Parse(String.Format("{0}{1:0000}", (int)buildStart.Subtract(BaseDifferenceDate).TotalDays, (int)buildStart.Subtract(dayStart).TotalMinutes));*/
            }

            return 0;
        }

        public static ManagedVersion ConvertFromString(string p)
        {
            ManagedVersion v = new ManagedVersion();

            string[] versionSegments = p.Split('.');

            // If we have the standard four-part version string (i.e., M.m.b.r),
            // then just automatically set our values
            if (versionSegments.Count() == 4)
            {
                v.MajorVersion = Int32.Parse(versionSegments[0]);
                v.MinorVersion = Int32.Parse(versionSegments[1]);
                v.Build = Int32.Parse(versionSegments[2]);
                v.Revision = Int32.Parse(versionSegments[3]);
            }
            else
            {
                // Hm. Crap.

                throw new Exception("Non-standard version format");
            }

            return v;
        }
    }
}
